package com.ruoyi.workflow.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.common.constant.ProcessConstants;
import com.ruoyi.flowable.common.constant.TaskConstants;
import com.ruoyi.flowable.common.enums.FlowComment;
import com.ruoyi.flowable.common.enums.ProcessStatus;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.utils.TaskUtils;
import com.ruoyi.workflow.domain.bo.WfTaskBo;
import com.ruoyi.workflow.service.IWfTaskService;
import org.apache.catalina.security.SecurityUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskService {

    /**
     * 启动第一个任务
     * 总结:
     * 根据流程实例id获取所有任务，判断每个任务的审批人是否为当前发起人，是就addComment（流程实例id，type，xxx+发起流程申请），最后将taskService.complete完成审批
     * @param processInstance 流程实例
     * @param variables 流程参数
     */
    @Override
    public void startFirstTask(ProcessInstance processInstance, Map<String, Object> variables) {
//      若第一个用户任务为发起人，则自动完成任务
//        首先通过实例id，获取次实例中的所有任务
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .list();
//        任务list不为空
        if (CollUtil.isNotEmpty(tasks)) {
//            获取发起人
            String userIdStr = (String) variables.get(TaskConstants.PROCESS_INITIATOR);
            identityService.setAuthenticatedUserId(TaskUtils.getUserId());
            for (Task task : tasks) {
                if (task.getAssignee().equals(userIdStr)) {
                    taskService.addComment( task.getId()
                            ,processInstance.getProcessInstanceId()
                            , FlowComment.NORMAL.getType()
                            , SecurityUtils.getLoginUser().getUser().getNickName()+"发起流程申请"
                    );
                    taskService.complete(task.getId(),variables);
                }
            }
        }


    }

    /**
     * 取消流程申请
     * @param bo
     */
    @Override
    public void stopProcess(WfTaskBo bo) {
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceId(bo.getProcInsId())
                .list();
//        没有任务，即代表没有启动，获取所有任务已经完成
        if (CollectionUtils.isEmpty(taskList)) {
            throw new RuntimeException("流程未启动或已执行完成,取消申请失败");
        }

//        根据id查询流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(bo.getProcInsId()).singleResult();
//        流程实例id查询表单BpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        if (Objects.nonNull(bpmnModel)) {
            Process process = bpmnModel.getMainProcess();
//            查询元素类型为结束事件的元素
            List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
            if (CollectionUtils.isNotEmpty(endNodes)) {
                Authentication.setAuthenticatedUserId(TaskUtils.getUserId());
//               根据流程实例id设置一个流程变量，常量名为PROCESS_STATUS_KEY，常量canceled
                runtimeService.setVariable(processInstance.getId(), ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.CANCELED.getStatus());
                for (Task task : taskList) {
                    taskService.addComment(task.getId(),processInstance.getProcessInstanceId(),FlowComment.STOP.getType(),"取消流程");
                }
//                获取当前流程最后一个节点
                String endId = endNodes.get(0).getId();
//                获取流程的执行实例（执行对象）
                List<Execution> executions = runtimeService.createExecutionQuery()
                        .parentId(processInstance.getProcessInstanceId())
                        .list();
                List<String> executionIds = new ArrayList<>();
                executions.forEach(execution -> executionIds.add(execution.getId()));
//                变更流程为已结束状态
                runtimeService.createChangeActivityStateBuilder()
                        .moveExecutionsToSingleActivityId(executionIds,endId)
                        .changeState();
            }
        }


    }
}
